﻿//
// *************************************************************************************
// WP-Framework
// 
// Developed by
// Lukas Kretschmar (lkretschmar.dev@bluewin.ch)
//
// Switzerland, Copyright (c) 2013 lkretschmar
// This content is released under the MIT License (http://opensource.org/licenses/MIT).
//     
// *************************************************************************************
//
//
			

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using KretschIT.WP_Fx.EasyMoq.Generator.Items;
using KretschIT.WP_Fx.EasyMoq.Generator.Tests.Helpers.Objects;
using KretschIT.WP_Fx.EasyMoq.Generator.Tests.Helpers.Objects.Custom;
using KretschIT.WP_Fx.EasyMoq.Generator.Tests.Helpers.Constraints;
using KretschIT.WP_Fx.EasyMoq.Generator.Tests.Helpers.Events;
using KretschIT.WP_Fx.EasyMoq.Generator.Tests.Helpers.Events.EventArgs;

namespace KretschIT.WP_Fx.EasyMoq.Generator.Tests.Items
{
    [TestClass]
    public class TypeCollectorTest
    {
        private ITypeCollector collector;

        [TestInitialize]
        public void Init()
        {
            this.collector = new TypeCollector();
        }

        [TestMethod]
        public void Test_UsedTypes_Simple()
        {
            var t = typeof(ITestObject);
            this.collector.Add(t);
            var usedTypes = this.collector.GetUsedTypesOf(t);
            
            Assert.AreEqual(5, usedTypes.Count());
            usedTypes.Contains(typeof(ITestObject));
            usedTypes.Contains(typeof(string));
            usedTypes.Contains(typeof(char));
            usedTypes.Contains(typeof(bool));
            usedTypes.Contains(typeof(IOtherNamespaceObject));
        }

        [TestMethod]
        public void Test_UsedTypes_Null()
        {
            this.collector.Add(null);
        }

        [TestMethod]
        public void Test_UsedTypes_OfNull()
        {
            var usedTypes = this.collector.GetUsedTypesOf(null);
            Assert.AreEqual(0, usedTypes.Count());
        }

        [TestMethod]
        public void Test_UsedTypes_IgnorGenericParameters()
        {
            var type = typeof(ITestEmptyGenericObject<int>);
            this.collector.Add(type);
            var usedTypes = this.collector.GetUsedTypesOf(type);

            Assert.AreEqual(2, usedTypes.Count());
            Assert.IsTrue(usedTypes.Contains(typeof(ITestEmptyGenericObject<>)));
            Assert.IsTrue(usedTypes.Contains(typeof(Int32)));
        }

        [TestMethod]
        public void Test_UsedTypes_SimpleGeneric()
        {
            var t = typeof(ITestSimpleGenericObject<>);
            this.collector.Add(t);
            var usedTypes = this.collector.GetUsedTypesOf(t);

            Assert.AreEqual(1, usedTypes.Count());
            usedTypes.Contains(typeof(ITestSimpleGenericObject<>));
        }

        [TestMethod]
        public void Test_UsedTypes_MergeDefinitions()
        {
            var typeInt = typeof(ITestSimpleGenericObject<int>);
            var typeBool = typeof(ITestSimpleGenericObject<bool>);
            var typeString = typeof(ITestSimpleGenericObject<string>);
            this.collector.Add(typeInt);
            this.collector.Add(typeBool);
            this.collector.Add(typeString);
            var usedTypes = this.collector.GetUsedTypesOf(typeBool);

            Assert.AreEqual(2, usedTypes.Count());
            Assert.IsTrue(usedTypes.Contains(typeof(ITestSimpleGenericObject<>)));
            Assert.IsTrue(usedTypes.Contains(typeof(bool)));
        }

        [TestMethod]
        public void Test_UsedTypes_ComplexGeneric()
        {
            var type = typeof(IVeryComplexGenericConstraint<,,>);
            this.collector.Add(type);
            var usedTypes = this.collector.GetUsedTypesOf(type);

            Assert.AreEqual(4, usedTypes.Count());
            Assert.IsTrue(usedTypes.Contains(typeof(IVeryComplexGenericConstraint<,,>)));
            Assert.IsTrue(usedTypes.Contains(typeof(IDictionary<,>)));
            Assert.IsTrue(usedTypes.Contains(typeof(IComplexGenericConstraint<,>)));
            Assert.IsTrue(usedTypes.Contains(typeof(IEnumerable<>)));
        }

        [TestMethod]
        public void Test_UsedTypes_GenericArguments()
        {
            var type = typeof(ITestComplexGenericObject<int, bool, string>);
            this.collector.Add(type);
            var usedTypes = this.collector.GetUsedTypesOf(type);

            Assert.AreEqual(5, usedTypes.Count());
            Assert.IsTrue(usedTypes.Contains(typeof(ITestComplexGenericObject<,,>)));
            Assert.IsTrue(usedTypes.Contains(typeof(Int32)));
            Assert.IsTrue(usedTypes.Contains(typeof(Boolean)));
            Assert.IsTrue(usedTypes.Contains(typeof(String)));
            Assert.IsTrue(usedTypes.Contains(typeof (IEnumerable<>)));
        }

        [TestMethod]
        public void Test_UsedTypes_GenericReturnTypes()
        {
            var type = typeof (ITestGenericReturnTypes<bool>);
            this.collector.Add(type);
            var usedTypes = this.collector.GetUsedTypesOf(type);

            Assert.AreEqual(3, usedTypes.Count());
            Assert.IsTrue(usedTypes.Contains(typeof(ITestGenericReturnTypes<>)));
            Assert.IsTrue(usedTypes.Contains(typeof(Boolean)));
            Assert.IsTrue(usedTypes.Contains(typeof(IEnumerable<>)));
        }

        [TestMethod]
        public void Test_UsedTypes_Events()
        {
            var type = typeof(ITestAllEvent);
            this.collector.Add(type);
            var usedTypes = this.collector.GetUsedTypesOf(type);

            Assert.AreEqual(6, usedTypes.Count());
            Assert.IsTrue(usedTypes.Contains(typeof(ITestAllEvent)));
            Assert.IsTrue(usedTypes.Contains(typeof(EventHandler)));
            Assert.IsTrue(usedTypes.Contains(typeof(EventHandler<>)));
            Assert.IsTrue(usedTypes.Contains(typeof(EventArgs)));
            Assert.IsTrue(usedTypes.Contains(typeof(CustomEventHandler<,>)));
            Assert.IsTrue(usedTypes.Contains(typeof(MyEventArgs)));
        }

        [TestMethod]
        public void Test_UsedTypes_GenericDefinition()
        {
            var type = typeof(ITestSimpleGenericObject<int>);
            this.collector.Add(type);
            var usedTypes = this.collector.GetUsedTypesOf(typeof(ITestSimpleGenericObject<>));

            Assert.AreEqual(0, usedTypes.Count());
        }

        [TestMethod]
        public void Test_NameOccursMoreThanOnce_False()
        {
            var type = typeof(ITestObject);
            this.collector.Add(type);
            Assert.IsFalse(this.collector.NameOccursMoreThanOnceOf(typeof(string)));
        }

        [TestMethod]
        public void Test_NameOccursMoreThanOnce_True()
        {
            var type = typeof(IMissUnderstandableGenericConstraint<,>);
            this.collector.Add(type);
            Assert.IsTrue(this.collector.NameOccursMoreThanOnceOf(typeof(ITestSimpleGenericObject<>)));
        }

        [TestMethod]
        public void Test_NameOccursMoreThanOnce_IgnoreGenericArguments()
        {
            var type = typeof(ITestSimpleGenericObject<>);
            this.collector.Add(type);
            Assert.IsFalse(this.collector.NameOccursMoreThanOnceOf(typeof(ITestSimpleGenericObject<int>)));
        }
    }
}
